/**
 * Created by rirong on 14-12-18.
 */

var  DataGo = require('./DataCenterGo')
	,DataCenterGo = DataGo.base
	,radon = require('radon')
	,util = radon.util
	,sysUtil = require('util')
	,MongoCriteria = require('./MongoCriteria').base
	,include = radon.use('Include');

var CONST = {
	'INCLUDE_MONGO_FIELDS': 1
	,'INCLUDE_METRIC_FIELDS': 2
};

function DataCenterParam(type) {
	var self = this;
	self.$type = type || '';	//查询的数据类型. todo 待补充
	self.$fields = [];	// 查询的字段
	self.$excludeFields = null;	//要排除的字段
	self.$fullRecord = false; // 固定要求返回所有记录, 包括空记录
	self.$order = {};	//设置排序的字段.
	self.$noMetrics = false;
	self.$page = 1;	//第几页
	self.$size = 20; //一页大小.
	self.$query = 'items,amount';//设置查询类型, 汇总和详细记录
	self.$keys = null; // 手动设置维度
	self.$zero = null;
	self.$zero_name_field = 'Name';


	self.$condition = null; //obj 条件集合, 一般来说是指标的条件过滤： cpc > 23, cpm <32, abc @ 3;4;5;6;7
	self.$dimCondition = null;//obj 维度条件集合
	self.$addOnCondition = null; //obj 与条件集合
	self.$metrics = false;
	self.$mongoFields = true;
	self.$aggregate = null;	//聚合条件.不包括match.
	self.dcConfig = DataGo.config;

	self.$MongoCriteria = new MongoCriteria();
	self.$timeZone = self.$MongoCriteria.$timeZone;
}

exports.base = DataCenterParam;

DataCenterParam.prototype.getOptions = function(isExport) {
	if(!this.$type) {
		return false;
	}

	var conf = this.dcConfig((isExport ? 'export.' : 'querys.')+ this.$type);
	if(!conf) {
		return false;
	}


	var opts = {
		'type': this.$type
		,'page': this.$page
		,'size': this.$size
		,'query_amount': this.$query.indexOf('amount') > -1
		,'query_items': this.$query.indexOf('items') > -1
		,'exclude_fields': this.$excludeFields
		,'full_record': this.$fullRecord
		,'keys': this.$keys
	};

	if(this.$mustKeys !== undefined)
	{
		opts.must_keys = this.$mustKeys;
	}
	if(this.$byGo !== undefined)
	{
		opts.byGo = this.$byGo;
	}
	if(this.$amountByGo !== undefined)
	{
		opts.amountByGo = this.$amountByGo;
	}

	if(this.$skipMetricCheck !== undefined)
	{
		opts.skipMetricCheck = this.$skipMetricCheck;
	}

	var fields = this.$fields;
	var mask;
	var defFlag;
	//没有设置metric,则不查询指标.
	if(this.$metrics !== true) {
		defFlag = (-1 & ~CONST.INCLUDE_METRIC_FIELDS);	//去掉合并指标的指示的.
		//把是查Mongo字段还是查metric字段 的标志位放在 fileds 的头部.[0]
		var flag = fields.shift();
		mask = sysUtil.isNumber(flag) ? (flag & defFlag) : defFlag;	//去掉合并指标的指示.


		if(fields && fields.length) {
			if(isNaN(+flag)) {
				fields.unshift(flag);
				fields.unshift(mask);
			}
			else {
				fields.unshift(mask);
			}
		}
		else {
			fields = [mask];
		}

		if(this.$metrics && this.$metrics.length) {
			Array.prototype.push.apply(fields, this.$metrics);
		}
	}

	if(this.$mongoFields !== true) {
		defFlag = (-1 & ~CONST.INCLUDE_MONGO_FIELDS);	// 去掉合并mongo的指示..
		flag = fields.shift();
		mask = sysUtil.isNumber(flag) ? flag & (defFlag) : defFlag;

		if(fields && fields.length) {
			if(isNaN(+flag)) {
				fields.unshift(flag);
				fields.unshift(mask);
			}
			else {
				fields.unshift(mask);
			}
		}
		else {
			fields = [mask];
		}

		if(this.$mongoFields && this.$mongoFields.length) {
			Array.prototype.push.apply(fields, this.$mongoFields);
		}
	}

	opts['fields'] = fields;
	fields = null;

	if(this.$order) {
		var order = '';
		for(var prop in this.$order) {
			if(this.$order.hasOwnProperty(prop)) {
				order += ',' + prop + '|' + (this.$order[prop] === 1 ? 1: 0);
			}
		}
		opts.order = order.substr(1);
		order = null;
	}

	opts.where = this.$MongoCriteria.getQuery();

	if(this.$condition) {
		opts.metric_where = this.$condition;
	}

	if(this.$dimCondition) {
		opts.dim_where = this.$dimCondition;
	}

	if(this.$addOnCondition) {
		opts.addon_where = this.$addOnCondition;
	}

	opts.base = this.$MongoCriteria.getTime();

	if(this.$aggregate) {
		opts.aggregate = this.$aggregate;
	}
	
	if(this.$zero) {
		opts.zero = this.$zero;
		opts.zero_name_field = this.$zero_name_field;
	}

	return opts;
};

/*
 * @param  object $param 类型参数
 * 	@param  String $field 类型参数
 * 	@param  Array $value  要设置的值.
 * 	@param  bool write	是读还是写操作.
 * 	@param  bool isArray 保存的值是不是数据.
 * 	@param  func format 格式化方法
 */
DataCenterParam.prototype._getSet = function(param) {
	var field = param.field;
	var value = param.value;
	var old = util.clone(this[field]);
	if(param.write) {
		if(param.isArray) {
			this[field] = sysUtil.isArray(value) ? value : value.split(',');
		}
		else if(param.func && sysUtil.isFunction(param.func)){
			this[field] = param.func(value);
		}
		else {
			this[field] = value;
		}
	}

	return old;
};

/**
 * 设置查询数据类型, 该类型会读取配置文件信息完善查询条件
 * @param  String $type 类型参数
 * @return String       返回原类型参数值
 */
DataCenterParam.prototype.type = function(value) {
	return this._getSet({
		field: '$type'
		,value: value
		,write: value !== undefined
	});
};



/**
 * 设置要查询的字段
 * @param  Array $fields 查询字段数组, 支持指标分组标识, 支持数组与以逗号为间隔的字符串.
 * @return Array         返回原查询字段设置值
 */
DataCenterParam.prototype.fields = function(value) {
	return this._getSet({
		field: '$fields'
		,value: value
		,write: value !== undefined
		,isArray: true
	});
};


DataCenterParam.prototype.excludeFields = function(value) {
	return this._getSet({
		field: '$excludeFields'
		,value: value
		,write: value !== undefined
		,isArray: true
	});
};


/**
 * 设置排序字段
 * @param  Object $order 排序字段设置
 * @return Array        返回原排序字段设置值
 */
DataCenterParam.prototype.order = function(value) {
	return this._getSet({
		field: '$order'
		,value: value
		,write: value !== undefined
	});
};


/**
 * 设置不查询指标统计数据
 * @param  Boolean $stat <可选> 是否不查询指标数据状态
 * @return Boolean       返回原不查询指标状态设置
 */
DataCenterParam.prototype.noMetrics = function(value) {
	return this._getSet({
		field: '$noMetrics'
		,value: !!value
		,write: value !== undefined
	});
};

/**
 * 设置查询数据分页
 * @param  Integer $page 分页页码
 * @return Integer       返回原分页页码
 */
DataCenterParam.prototype.page = function(value) {
	return this._getSet({
		field: '$page'
		,value: +value
		,write: value !== undefined
	});
};




/**
 * 设置查询分页大小
 * @param  Integer $size 分页大小
 * @return Integer       返回原分页大小
 */
DataCenterParam.prototype.size = function(value) {
	return this._getSet({
		field: '$size'
		,value: +value
		,write: value !== undefined
	});
};

/**
 * 设置查询类型, 汇总和详细记录
 * @param  String $query 查询类型, 逗号分隔字符串, 可支持items,amount
 * @return String        返回原查询类型值
 */
DataCenterParam.prototype.query = function(value) {
	return this._getSet({
		field: '$query'
		,value: value
		,write: value !== undefined
	});
}


DataCenterParam.prototype.fullRecord = function(stat) {
	this.$fullRecord = !!stat;
};

DataCenterParam.prototype.setKeys = function(value) {
	this.$keys = value;
};

DataCenterParam.prototype.mustKeys = function(value) {
	this.$mustKeys = +value;
};

DataCenterParam.prototype.filterZero = function(name, field) {
	this.$zero = name;
	this.$zero_name_field = field || this.$zero_name_field;
};

DataCenterParam.prototype.queryByGo = function(value) {
	this.$byGo = !!value;
};

DataCenterParam.prototype.amountByGo = function(value) {
	this.$amountByGo = !!value;
};

DataCenterParam.prototype.skipMetricCheck = function(value) {
	this.$skipMetricCheck = !!value;
};

/**
 * 设置要查询的指标
 * @param  String value  数组值['click_rate', 'bid_num'] 或者 'click_rate,bid_num'
 * @return String        返回原查询类型值
 */
DataCenterParam.prototype.metricField = function(value) {
	if(value == 'false') {
		value = false;
	}
	else if(value == 'true') {
		value = true;
	}

	if(sysUtil.isString(value)) {
		value = value.split(',');
	}

	return this._getSet({
		field: '$metrics'
		,value: value
		,write: value !== undefined
	});
};

/**
 * 设置要查询的mongo字段,
 * @param  String value  数组值['Name', 'Labels'] 或者 'Name,Labels'
 * @return String        返回原查询类型值
 */
DataCenterParam.prototype.mongoField = function(value) {
	if(value == 'false') {
		value = false;
	}
	else if(value == 'true') {
		value = true;
	}

	if(sysUtil.isString(value)) {
		value = value.split(',');
	}

	return this._getSet({
		field: '$mongoFields'
		,value: value
		,write: value !== undefined
	});
};

/**
 * 添加指标查询条件
 * @param  Mix     $cond   过滤条件字符串 / 数组的直接过滤条件参数
 * @param  boolean $append <可选> 是否附加条件, flase表示覆盖
 * @return Array           返回原来的过滤条件
 * 当value 为空, append为false时,清空条件.
 */
DataCenterParam.prototype.addCond = function(value, append) {
	var old = util.clone(this.$condition);
	if(append === undefined) {
		append = true;
	}
	if(value || !append) {
		value = this.formatCondition(value);
		if(append) {
			if(!this.$condition) {
				this.$condition = {};
			}
			util.extend(this.$condition, value);
		}
		else {
			this.$condition = value;
		}
	}

	return old;
};

DataCenterParam.prototype.getCond = function(name) {
	if (name)
	{
		return (this.$condition && this.$condition.hasOwnProperty(name)) ? this.$condition[name] : null;
	}
	else
	{
		return this.$condition;
	}
};

/**
 * 添加维度指标查询条件
 * @param  Array   $cond   维度指标过滤条件参数数组对象
 * @param  boolean $append <可选> 是否附加条件, flase表示覆盖
 * @return Array           返回原来的过滤条件
 * 当value 为空, append为false时,清空条件.
 */
DataCenterParam.prototype.addDimCond = function(value, append) {
	return this._addCond('$dimCondition', value, append);
};

/**
 * 添加维度指标附加查询条件
 * @param  Array   $cond   维度指标过滤条件参数数组对象
 * @param  boolean $append <可选> 是否附加条件, flase表示覆盖
 * @return Array           返回原来的过滤条件
 */
DataCenterParam.prototype.addAddOnCond = function(value, append) {
	return this._addCond('$addOnCondition', value, append);
};

DataCenterParam.prototype._addCond = function(field, value, append) {
	var old = util.clone(this[field]);
	if(append === undefined) {
		append = true;
	}
	if(value || !append) {
		if(append && util.isPlainObject(value)) {
			if(!this[field]) {
				this[field] = {};
			}
			util.extend(this[field], value);
		}
		else {
			this[field] = value;
		}
	}

	return old;
};


/*
	格式化条件
	@param mix value
		value 如果是对象,就直接返回
			  如果是字符串,格式如下: 'cpm >= 32, cpa |42, cpp @32;43;5;23' , 以逗号为分割,以@就特殊一点.
	@return object 返回的是对象如 {cpm: {$gte: 32}, cpa: 42, cpp: {$in: [32,43,5,23]}}
 */
DataCenterParam.prototype.formatCondition = function(value) {
	if(!value){
		return {};
	}
	if(util.isPlainObject(value)) {
		return value;
	}

	var where = {};
	var map = {
		'>=': '$gte'
		,'>': '$gt'
		,'=<': '$lte'
		,'<': '$lt'
		,'|': '='
		,'<>': '$ne'
		,'@': '$in'
	};

	if(value && sysUtil.isString(value)) {
		try {
			value = JSON.parse(value);
		}
		catch(e) {}
	}

	if(sysUtil.isArray(value)) {
		value.forEach(function(v) {
			//子表格condition的id为64位问题。
			for (var key in v)
			{
				if (include && include.Number && sysUtil.isString(v[key]))
				{
					v[key] = include.Number(v[key]);
				}
			}
			util.extend(where, v);
		});
	}
	else {
		var list = value.trim().split(',');
		list.forEach(function(item) {
			var op, cond, query = {};
			item = item.trim().split(/\s*(>=|>|=<|<|@|<>|\|)\s*/);
			if(item.length === 3) {
				op = item[1];
				if(map[op]) {
					op = map[op];
					cond = item[2];
					var tmpCOnd = +cond;
					if(sysUtil.isNumber(tmpCOnd) && !isNaN(tmpCOnd)) {
						cond = +cond;
						if(op == '$in' || op == '=') {
							where[item[0]] = cond;
						}else {
							query[op] = cond;
							where[item[0]] = query
						}
					}
					else if(op == '$in' && cond.match(/^(\d+)(;\d+)*$/)) {
						// in条件处理, 只包含整数ID
						query[op] = util.format.semiIds(cond);
						where[item[0]] = query;
					}
				}
			}
		});
	}


	return where;
};

/**
 * 获取所有有效指标字段
 * @return Array 返回有效指标字段名称数组
 */
var G_metric;
DataCenterParam.prototype.getMetricsFields = function() {
	//todo 待
	if(!G_metric) {
		var data = this.dcConfig('metrics');
		if(data) {
			var keys = Object.keys(data);
			var list = [];
			var keyMetric = [];
			keys.forEach(function(key) {
				Array.prototype.push.apply(list, data[key]);
				keyMetric.push('{'+ key +'}');
			});

			Array.prototype.push.apply(list, keyMetric);
			G_metric = list;
		}
	}

	return G_metric;
};

DataCenterParam.prototype.addAnd = function() {
	this.$MongoCriteria.addAnd.apply(this.$MongoCriteria, arguments);
	return this;
};

DataCenterParam.prototype.removeAnd = function() {
	return this.$MongoCriteria.removeAnd.apply(this.$MongoCriteria, arguments);
};

DataCenterParam.prototype.getAnd = function() {
	return this.$MongoCriteria.getAnd.apply(this.$MongoCriteria, arguments);
};

DataCenterParam.prototype.addOr = function() {
	this.$MongoCriteria.addOr.apply(this.$MongoCriteria, arguments);
	return this;
};

DataCenterParam.prototype.removeOr = function() {
	return this.$MongoCriteria.removeOr.apply(this.$MongoCriteria, arguments);
};

DataCenterParam.prototype.getOr = function() {
	return this.$MongoCriteria.getOr.apply(this.$MongoCriteria, arguments);
};

DataCenterParam.prototype.begin = function() {
	return this.$MongoCriteria.begin.apply(this.$MongoCriteria, arguments);
};

DataCenterParam.prototype.end = function() {
	return this.$MongoCriteria.end.apply(this.$MongoCriteria, arguments);
};


DataCenterParam.prototype.aggregate = function(value) {
	return this._getSet({
		field: '$aggregate'
		,value: value
		,write: value !== undefined
	});
};

DataCenterParam.prototype.toTimestamp = function() {
	return this.$MongoCriteria.toTimestamp.apply(this.$MongoCriteria, arguments);
};

